package com.加载与反射机制;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;

public class 加载与反射 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchFieldException {

        //系统类加载器
        ClassLoader cl = ClassLoader.getSystemClassLoader();

        //平台类加载器
        ClassLoader pt = cl.getParent();

        //内置类加载器
        ClassLoader nzl = pt.getParent();

        //获取class类对象的三种方式
        Class<Test> cs1 = Test.class;
        Class<?> cs2 = Class.forName("com.加载与反射机制.Test");
        Test t = new Test();
        Class<?> cs3 = t.getClass();

        //返回所有公共构造方法对象的数组
        Constructor<?>[] con1 = cs1.getConstructors();

        //返回所有构造方法对象的数组
        Constructor<?>[] con2 = cs1.getDeclaredConstructors();

        //返回单个公共构造方法对象
        Constructor<?> con3 = cs1.getConstructor();

        //返回单个构造方法对象
        Constructor<?> con4 = cs1.getDeclaredConstructor();

        //利用指定的构造方法产生的对象
        //值为true，取消访问检查
        con4.setAccessible(true);
        Object obj = con4.newInstance();
        //Object obj = con.newInstance("林青霞", 30, "西安");

        //返回所有公共成员变量对象的数组
        Field[] fd1 = cs1.getFields();

        //返回所有成员变量对象的数组
        Field[] fd2 = cs1.getDeclaredFields();

        //返回单个公共成员变量对象
        Field fd3 = cs1.getField("name");

        //返回单个成员变量对象
        Field fd4 = cs1.getDeclaredField("name");
        fd4.setAccessible(true);
        fd4.set(obj, 123);

        //返回所有公共成员方法对象的数组，包括继承的
        Method[] md1 = cs1.getMethods();

        //返回所有成员方法对象的数组，不包括继承的
        Method[] md2 = cs1.getDeclaredMethods();

        //返回公共成员方法对象，包括继承的
        Method md3 = cs1.getMethod("getName");

        //返回成员方法对象，不包括继承的
        Method md4 = cs1.getDeclaredMethod("setName", int.class);

        //调用方法
        md4.invoke(obj,22);

        //通过反射技术，向一个泛型为Integer的集合中添加一些字符串数据
        ArrayList<Integer> list = new ArrayList<Integer>();
//        list.add(12);
//        list.add(22);
//        list.add(32);
//        list.add("hello");
        Class<? extends  ArrayList> ca=list.getClass();
        Method md=ca.getMethod("add",Object.class);
        md.invoke(list,"hello");
        md.invoke(list,"world");
        md.invoke(list,"i love you");
        System.out.println(list);

    }
}
